class Order < ActiveRecord::Base
  
  include DynamicDefaultScoping
  
  validates :order_no, :uniqueness => true
  validates :enterprise_id, :presence => true
#  validates :sale_price,
#    :order_price,
#    :numericality => {
#      :greater_than_or_equal_to => 0
#    },:on => :update

  belongs_to :created_by_user, :class_name => 'User', :foreign_key => :created_by_user_id
  belongs_to :updated_by_user, :class_name => 'User', :foreign_key => :updated_by_user_id
  belongs_to :being_edited_by_user, :class_name => 'User', :foreign_key => :being_edited_by_user_id
  belongs_to :effected_by_user, :class_name => 'User', :foreign_key => :effected_by_user_id
  belongs_to :blanked_out_by_user, :class_name => 'User', :foreign_key => :blanked_out_by_user_id
  belongs_to :filed_by_user, :class_name => 'User', :foreign_key => :filed_by_user_id
  belongs_to :enterprise
  has_many :order_items
  has_many :visible_order_to_groups
  has_many :visible_order_to_users

  default_scope :current_enterprise,lambda { 
    where(
      :enterprise_id => Enterprise.current_id 
    ).order(
      'feeded_at desc, created_at desc'
    ).try(User.current.is_admin? ? 'escaped_visible_scope' : 'by_visible_scope')
  }
  
  scope :by_visible_scope, lambda { 
    where(
      "(visible_scope = ? and created_by_user_id = ? ) or (visible_scope = ? ) or (visible_scope = ? and id in (?) ) or (visible_scope = ? and id in (?))",
      'myself',
      User.current_id,
      'everyone',
      'groups',
      # 所有
      VisibleOrderToGroup.select('DISTINCT  order_id').where( 'group_id in (?)', User.current.group_ids.uniq).each_with_object([]) {|visible,order_id| order_id << visible.order_id }.join('，'),
      'users',
      VisibleOrderToUser.select('DISTINCT order_id').where( 'user_id = ?', User.current_id).each_with_object([]) {|visible,order_id| order_id << visible.order_id }.join('，')
  )}
  
  scope :escaped_visible_scope, lambda { where('visible_scope is not null') }
  
  scope :being_edited, lambda { where(:status => 'being_edited') }
  scope :effected, lambda { where(:status => 'effected') }
  scope :blanked_out, lambda { where(:status => 'blanked_out') }
  scope :filed, lambda { where(:status => 'filed') }
  scope :has_been_ordered, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::OrderItemCreated'))}
  scope :has_been_entered, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::EnterCreated'))}
  scope :after_serviced, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::InstallAfterServiced'))}
  scope :has_been_sent_to_factory, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::OrderMadeCreated'))}
  scope :has_been_sent_to_installer, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::InstallCreated'))}
  scope :has_been_installed, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::Installed'))}
  scope :has_been_completed, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::OrderItemCompleted'))}
  scope :has_been_payment, lambda{where('id in (?)', OrderItem.order_ids_by_feed_type('Feed::PaymentCreated'))}
  scope :being_edited_or_effected, lambda{where('status = ? or status = ?','being_edited','effected')}
  
  # 有尾款的
  scope :has_balanced, lambda { where(' (sale_price - order_price - gathered_balance) > 0').being_edited_or_effected }

  # 有进展
  scope :feeded_in_near_one_week, lambda{ where( 'feeded_at >=? and feeded_at <= ?',1.weeks.ago,Time.now ).being_edited_or_effected }
  scope :feeded_in_near_half_month, lambda{ where( 'feeded_at >=? and feeded_at <= ?',15.days.ago,Time.now ).being_edited_or_effected }
  scope :feeded_in_near_one_month, lambda{ where( 'feeded_at >=? and feeded_at <= ?',1.months.ago,Time.now ).being_edited_or_effected }
  scope :feeded_at_one_month_ago, lambda{ where( 'feeded_at <= ?',1.months.ago ).being_edited_or_effected }

  # 无进展
  scope :no_feeded_in_near_one_week, lambda{ where( 'feeded_at < ?',1.weeks.ago ).being_edited_or_effected }
  scope :no_feeded_in_near_half_month, lambda{ where( 'feeded_at < ?',15.days.ago).being_edited_or_effected }
  scope :no_feeded_in_near_one_month, lambda{ where( 'feeded_at < ?',1.months.ago).being_edited_or_effected }

  # 即将交货
  scope :delivered_near_one_week, lambda { where('deliveried_on >= ? and deliveried_on <= ? ', Time.now, 1.weeks.from_now).being_edited_or_effected }
  scope :delivered_near_half_month, lambda { where('deliveried_on >= ? and deliveried_on <= ? ', Time.now, 15.days.from_now).being_edited_or_effected }
  scope :delivered_near_one_month, lambda { where('deliveried_on >= ? and deliveried_on <= ? ', Time.now, 1.months.from_now).being_edited_or_effected }
  scope :delivered_after_one_month, lambda { where('deliveried_on >= ? ', 1.weeks.from_now).being_edited_or_effected }
  scope :delivered_on, lambda { |delivered_on| where('deliveried_on = ? ', delivered_on).being_edited_or_effected }
  scope :delivered_on_month, lambda {|year,month| where('deliveried_on >= ? and deliveried_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }

  # 逾期交货
  scope :overdue_delivered_near_one_week, lambda { where('deliveried_on <= ? and deliveried_on >= ? ', Time.now, 1.weeks.ago).being_edited_or_effected }
  scope :overdue_delivered_near_half_month, lambda { where('deliveried_on <= ? and deliveried_on >= ? ', Time.now, 15.days.ago).being_edited_or_effected }
  scope :overdue_delivered_near_one_month, lambda { where('deliveried_on <= ? and deliveried_on >= ? ', Time.now, 1.months.ago).being_edited_or_effected }
  scope :overdue_delivered_more_than_one_month, lambda { where('deliveried_on <= ? ', 1.weeks.ago).being_edited_or_effected }
  scope :overdue_delivered_on, lambda { |delivered_on| where('deliveried_on = ? ', delivered_on).being_edited_or_effected }
  scope :overdue_delivered_on_month, lambda {|year,month| where('deliveried_on >= ? and deliveried_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }

  # 预订
  scope :ordered_in_near_one_week, lambda{ where( 'ordered_on >=? and ordered_on <= ?',1.weeks.ago,Time.now ).being_edited_or_effected }
  scope :ordered_in_near_half_month, lambda{ where( 'ordered_on >=? and ordered_on <= ?',15.days.ago,Time.now ).being_edited_or_effected }
  scope :ordered_in_near_one_month, lambda{ where( 'ordered_on >=? and ordered_on <= ?',1.months.ago,Time.now ).being_edited_or_effected }
  scope :ordered_at_one_month_ago, lambda{ where( 'ordered_on <= ?',1.months.ago ).being_edited_or_effected }
  scope :ordered_on, lambda{ |ordered_on| where( 'date(ordered_on) = ?',ordered_on ).being_edited_or_effected }
  scope :ordered_on_month, lambda {|year,month| where('ordered_on >=? and ordered_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }

  # 作废
  scope :blanked_out_in_near_one_week, lambda{ where( 'date(blanked_out_at) >=? and date(blanked_out_at) <= ?',1.weeks.ago,Time.now ).blanked_out }
  scope :blanked_out_in_near_half_month, lambda{ where( 'date(blanked_out_at) >=? and blanked_out_at <= ?',15.days.ago,Time.now ).blanked_out }
  scope :blanked_out_in_near_one_month, lambda{ where( 'date(blanked_out_at) >=? and blanked_out_at <= ?',1.months.ago,Time.now ).blanked_out }
  scope :blanked_out_at_one_month_ago, lambda{ where( 'date(blanked_out_at) <= ?',1.months.ago ).blanked_out }
  scope :blanked_out_on, lambda { |blanked_out_on| where('date(blanked_out_at) = ?',blanked_out_on).blanked_out }
  scope :blanked_out_on_month, lambda {|year,month| where('date(blanked_out_at) >=? and date(blanked_out_at) <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).blanked_out }

  # 归档
  scope :filed_in_near_one_week, lambda{ where( 'date(filed_at) >=? and date(filed_at) <= ?',1.weeks.ago,Time.now ).filed }
  scope :filed_in_near_half_month, lambda{ where( 'date(filed_at) >=? and date(filed_at) <= ?',15.days.ago,Time.now ).filed }
  scope :filed_in_near_one_month, lambda{ where( 'date(filed_at) >=? and date(filed_at) <= ?',1.months.ago,Time.now ).filed }
  scope :filed_at_one_month_ago, lambda{ where( 'date(filed_at) <= ?',1.months.ago ).filed }
  scope :filed_on, lambda { |filed_on| where('date(filed_at) = ?',filed_on).filed }
  scope :filed_on_month, lambda {|year,month| where('date(filed_at) >=? and date(filed_at) <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).filed }

  # 上门安装
  scope :installed_in_near_one_week, lambda { where('installed_on <= ? and installed_on >= ? ', Time.now, 1.weeks.ago).being_edited_or_effected }
  scope :installed_in_near_half_month, lambda { where('installed_on <= ? and installed_on >= ? ', Time.now, 15.days.ago).being_edited_or_effected }
  scope :installed_in_near_one_month, lambda { where('installed_on <= ? and installed_on >= ? ', Time.now, 1.months.ago).being_edited_or_effected }
  scope :installed_at_one_month_ago, lambda { where('installed_on <= ? ', 1.weeks.ago).being_edited_or_effected }
  scope :installed_on, lambda { |installed_on| where('installed_on = ? ', installed_on).being_edited_or_effected }
  scope :installed_on_month, lambda {|year,month| where('installed_on >=? and installed_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }

  # 售后服务
  scope :after_serviced_in_near_one_week, lambda { where('after_serviced_on <= ? and after_serviced_on >= ? ', Time.now, 1.weeks.ago).being_edited_or_effected }
  scope :after_serviced_in_near_half_month, lambda { where('after_serviced_on <= ? and after_serviced_on >= ? ', Time.now, 15.days.ago).being_edited_or_effected }
  scope :after_serviced_in_near_one_month, lambda { where('after_serviced_on <= ? and after_serviced_on >= ? ', Time.now, 1.months.ago).being_edited_or_effected }
  scope :after_serviced_at_one_month_ago, lambda { where('after_serviced_on <= ? ', 1.weeks.ago).being_edited_or_effected }
  scope :after_serviced_on, lambda { |after_serviced_on| where('after_serviced_on = ? ', after_serviced_on).being_edited_or_effected }
  scope :after_serviced_on_month, lambda {|year,month| where('after_serviced_on >=? and after_serviced_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }

  # 厂家订做
  scope :order_made_in_near_one_week, lambda { where('order_made_on <= ? and order_made_on >= ? ', Time.now, 1.weeks.ago).being_edited_or_effected }
  scope :order_made_in_near_half_month, lambda { where('order_made_on <= ? and order_made_on >= ? ', Time.now, 15.days.ago).being_edited_or_effected }
  scope :order_made_in_near_one_month, lambda { where('order_made_on <= ? and order_made_on >= ? ', Time.now, 1.months.ago).being_edited_or_effected }
  scope :order_made_at_one_month_ago, lambda { where('order_made_on <= ? ', 1.weeks.ago).being_edited_or_effected }
  scope :order_made_on, lambda { |order_made_on| where('order_made_on = ? ', order_made_on).being_edited_or_effected }
  scope :order_made_on_month, lambda {|year,month| where('order_made_on >=? and order_made_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }

  # 支付
  scope :payed_in_near_one_week, lambda { where('payed_on <= ? and payed_on >= ? ', Time.now, 1.weeks.ago).being_edited_or_effected }
  scope :payed_in_near_half_month, lambda { where('payed_on <= ? and payed_on >= ? ', Time.now, 15.days.ago).being_edited_or_effected }
  scope :payed_in_near_one_month, lambda { where('payed_on <= ? and payed_on >= ? ', Time.now, 1.months.ago).being_edited_or_effected }
  scope :payed_at_one_month_ago, lambda { where('payed_on <= ? ', 1.weeks.ago).being_edited_or_effected }
  scope :payed_on, lambda { |payed_on| where('payed_on = ? ', payed_on).being_edited_or_effected }
  scope :payed_on_month, lambda {|year,month| where('payed_on >=? and payed_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }

  # 入库登记
  scope :entered_in_near_one_week, lambda { where('entered_on <= ? and entered_on >= ? ', Time.now, 1.weeks.ago).being_edited_or_effected }
  scope :entered_in_near_half_month, lambda { where('entered_on <= ? and entered_on >= ? ', Time.now, 15.days.ago).being_edited_or_effected }
  scope :entered_in_near_one_month, lambda { where('entered_on <= ? and entered_on >= ? ', Time.now, 1.months.ago).being_edited_or_effected }
  scope :entered_at_one_month_ago, lambda { where('entered_on <= ? ', 1.weeks.ago).being_edited_or_effected }
  scope :entered_on, lambda { |entered_on| where('entered_on = ? ', entered_on).being_edited_or_effected }
  scope :entered_on_month, lambda {|year,month| where('entered_on >=? and entered_on <= ? ',Date.parse("#{year}-#{month}-1"),Date.parse("#{year}-#{month}-1").at_end_of_month).being_edited_or_effected }


  def reset_after_serviced_cost!
    update_attributes! :after_serviced_cost => OrderItem.where(:order_id => id).sum(:after_serviced_cost)
  end
  
  before_create do |order|
    order.being_edited_by_user_id = User.current_id
  end

  after_update do |order|
    if order.visible_scope == "everyone" || order.visible_scope == "myself"
      VisibleOrderToGroup.destroy_by_order_id(order.id)
      VisibleOrderToUser.destroy_by_order_id(order.id)
    end
  end

  def init_order_no
    self.order_no ||= "OD#{DateTime.now.to_formatted_s(:number)}"
  end

  def effected!
    self.attributes =  {
      :status => 'effected',
      :effected_by_user_id => User.current_id
    }
    save(:validate => false)
  end

  def being_edited!
    self.attributes =  {
      :status => 'being_edited',
      :being_edited_by_user_id => User.current_id
    }
    save(:validate => false)
  end

  def blanked_out!
    self.attributes = {
      :status => 'blanked_out',
      :blanked_out_by_user_id => User.current_id,
      :blanked_out_at => Time.now
    }
    save(:validate => false)
  end

  def filed!
    self.attributes = {
      :status => 'filed',
      :filed_by_user_id => User.current_id,
      :filed_at => Time.now
    }
    save(:validate => false)
  end

  def reset_feeded_at!
    update_attributes :feeded_at => Feed.where('order_items.order_id = ?', id).includes(:order_item).order('feeds.updated_at desc').first.try(:updated_at)
  end

  def status
    ActiveSupport::StringInquirer.new(self[:status])
  end
  
  def visible_scope
    ActiveSupport::StringInquirer.new(self[:visible_scope])
  end
  
  # 是否其他用户正在编辑？
  def being_edited_by_other_user?
    status.being_edited? && User.current.id != being_edited_by_user_id
  end

  # 可否当前登录用户编辑？
  def can_be_edited_by_current_user?
    status.being_edited? && User.current.id == being_edited_by_user_id
  end

  # 待收尾款
  def balance
    sale_price - order_price - gathered_balance
  end

  #reset 已收尾款
  def reset_gathered_balance!
    self.gathered_balance = (Installation.gathered_balance(id) + AfterService.gathered_balance(id))
    save(false)
  end

  def how_much
    OrderMadePayment.how_much_sum(id)
  end
  
  def completed_ratio
    order_items.any? ? (order_items.completed.size * 1.0 / order_items.size) : 0
  end
  
  def completed_percent
    (completed_ratio * 100).to_i 
  end
  
  def order_items_completed?
    completed_percent == 100
  end
  
  # 谁可见该单
  def who_can_see
    case
    when visible_scope.myself?
      [User.current]
    when visible_scope.everyone?
      Enterprise.current.users
    when visible_scope.groups?
      visible_order_to_groups.each_with_object([Enterprise.current.admin]) do |visible_order_to_group, users|
        visible_order_to_group.group.users.each do |user|
          users << user if not users.include?(user)
        end
      end
    when visible_scope.users?
      visible_order_to_users.each_with_object([Enterprise.current.admin]) do |visible_order_to_user, users|
        users << visible_order_to_user.user if not users.include?(visible_order_to_user.user)
      end
    else
      raise "不支持的类型:#{visible_scope}"
    end    
  end

  def groups
    visible_order_to_groups.each_with_object([]) do |order_to_group, values|
      values << order_to_group.group
    end
  end

  def users
    visible_order_to_users.each_with_object([]) do |order_to_user, values|
      values << order_to_user.user
    end
  end

end
